package com.jinyang.plugindemo.hook.iactivitymanager;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.google.gson.Gson;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: LiuJinYang
 * @CreateDate: 2021/12/15
 * @Description: 用代理类IActivityManagerProxy来替换IActivityManager
 */
public class HookHelper {
    public static final String TARGET_INTENT = "target_intent";
    public static void hookAMS() {
        try {
            Object singleTon = null;

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                /*
                 * android 29或以上版本的API
                 */
                @SuppressLint("PrivateApi")
                Class<?> activityManagerClass = Class.forName("android.app.ActivityTaskManager");
                Field iActivityManagerSingletonField = activityManagerClass.getDeclaredField("IActivityTaskManagerSingleton");
                iActivityManagerSingletonField.setAccessible(true);
                singleTon = iActivityManagerSingletonField.get(null);

            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                /*
                 * android 26或以上版本的API是一样的
                 */
                Class<?> activityManagerClass = Class.forName("android.app.ActivityManager");
                Field iActivityManagerSingletonField = activityManagerClass.getDeclaredField("IActivityManagerSingleton");
                iActivityManagerSingletonField.setAccessible(true);
                singleTon = iActivityManagerSingletonField.get(null);
            } else {
                /*
                 *  android 26或以下版本的API是一个系列
                 */
                Class<?> activityManagerClass = Class.forName("android.app.ActivityManagerNative");
                Field iActivityManagerSingletonField = activityManagerClass.getDeclaredField("gDefault");
                iActivityManagerSingletonField.setAccessible(true);
                singleTon = iActivityManagerSingletonField.get(null);
            }


            Class<?> singleTonClass = Class.forName("android.util.Singleton");
            Field mInstanceField = singleTonClass.getDeclaredField("mInstance");
            mInstanceField.setAccessible(true);

            // 获取到IActivityManagerSingleton的对象
            final Object iActivityManager = mInstanceField.get(singleTon);

            Class<?> iActivityManagerClass;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                iActivityManagerClass = Class.forName("android.app.IActivityTaskManager");
            } else {
                iActivityManagerClass = Class.forName("android.app.IActivityManager");
            }

            Object newInstance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    new Class[]{iActivityManagerClass},
                    (o, method, args) -> {
                        Log.d("LJY_LOG", "IActivityManagerProxy: invoke>>>>>>>>>>>>>>>>>>> "+method.getName());
                        if ("startActivity".equals(method.getName())) {
                            Log.d("LJY_LOG", "IActivityManagerProxy: startActivity");
                            //拦截startActivity方法，接着获取参数args中第一个Intent对象，它是原本要启动插件Plugin002Activity的Intent
                            Intent intent = null;
                            int index = 0;
                            for (int i = 0; i < args.length; i++) {
                                if (args[i] instanceof Intent) {
                                    index = i;
                                    break;
                                }
                            }
                            Log.d("LJY_LOG","index:"+index);
                            intent = (Intent) args[index];
                            //新建一个subIntent用来启动的StubActivity
                            Intent subIntent = new Intent();
                            String packageName = "com.jinyang.plugindemo";
                            subIntent.setClassName(packageName, packageName + ".hook.StubHookActivity");
                            //将这个Plugin002Activity的Intent保存到subIntent中，便于以后还原Plugin002Activity
                            subIntent.putExtra(HookHelper.TARGET_INTENT, intent);
                            //用subIntent赋值给参数args，这样启动的目标就变为了StubActivity，用来通过AMS的校验。
                            Log.d("LJY_LOG","subIntent:"+new Gson().toJson(subIntent));
                            args[index] = subIntent;
                        }
                        Log.d("LJY_LOG", "IActivityManagerProxy: mActivityManager:"+iActivityManager);
                        Log.d("LJY_LOG", "IActivityManagerProxy: args:"+new Gson().toJson(args));
                        Log.d("LJY_LOG", "IActivityManagerProxy: method.invoke");
                        return method.invoke(iActivityManager, args);
                    });

            mInstanceField.set(singleTon, newInstance);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void hookHandler() {
        try {
            // 获取ActivityThread实例
            final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Field activityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
            activityThreadField.setAccessible(true);
            final Object activityThread = activityThreadField.get(null);
            // 获取Handler实例
            Field mHField = activityThreadClass.getDeclaredField("mH");
            mHField.setAccessible(true);
            Object mH = mHField.get(activityThread);
            Class<?> handlerClass = Class.forName("android.os.Handler");
            Field mCallbackField = handlerClass.getDeclaredField("mCallback");
            mCallbackField.setAccessible(true);
            mCallbackField.set(mH, (Handler.Callback) msg -> {
                switch (msg.what) {
                    case 100: // API 28 以前直接接收
                        try {
                            // 获取ActivityClientRecord中的intent对象
                            Field intentField = msg.obj.getClass().getDeclaredField("intent");
                            intentField.setAccessible(true);
                            Intent proxyIntent = (Intent) intentField.get(msg.obj);
                            // 拿到插件的Intent
                            Intent intent = proxyIntent.getParcelableExtra(TARGET_INTENT);
                            // 替换回来
                            proxyIntent.setComponent(intent.getComponent());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        break;
                    case 159: // API 28 以后加入了 lifecycle， 这里msg发生了变化
                        try {
                            Field mActivityCallbacksField = msg.obj.getClass().getDeclaredField("mActivityCallbacks");
                            mActivityCallbacksField.setAccessible(true);
                            List<Object> mActivityCallbacks = (List<Object>) mActivityCallbacksField.get(msg.obj);
                            for (int i = 0; i < mActivityCallbacks.size(); i++) {
                                Class<?> itemClass = mActivityCallbacks.get(i).getClass();
                                Log.d("LJY_LOG","itemClass:"+itemClass);
                                if (itemClass.getName().equals("android.app.servertransaction.LaunchActivityItem")) {
                                    Field intentField = itemClass.getDeclaredField("mIntent");
                                    intentField.setAccessible(true);
                                    Intent proxyIntent = (Intent) intentField.get(mActivityCallbacks.get(i));
                                    Intent intent = proxyIntent.getParcelableExtra(TARGET_INTENT);
                                    proxyIntent.setComponent(intent.getComponent());
                                    break;
                                }
                            }
                        } catch (Exception e) {
                            Log.d("LJY_LOG", "e = " + e.getMessage());
                        }
                        break;
                    default:
                        break;
                }
                return false;// 这里必须返回false
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}